package sg.edu.nus.iss.jass.controller;

import java.util.List;

import sg.edu.nus.iss.jass.constant.ActionBtnContants;
import sg.edu.nus.iss.jass.constant.ErrorConstants;
import sg.edu.nus.iss.jass.datastore.exception.DataStoreException;
import sg.edu.nus.iss.jass.dto.Company;
import sg.edu.nus.iss.jass.dto.GeographicalLocation;
import sg.edu.nus.iss.jass.dto.JobAdvert;
import sg.edu.nus.iss.jass.dto.SearchCriteria;
import sg.edu.nus.iss.jass.dto.Skill;
import sg.edu.nus.iss.jass.dto.SkillReference;
import sg.edu.nus.iss.jass.gui.DefaultActionPanel;
import sg.edu.nus.iss.jass.gui.HeaderPanel;
import sg.edu.nus.iss.jass.gui.JobSearchFormPanel;
import sg.edu.nus.iss.jass.gui.MainFrame;
import sg.edu.nus.iss.jass.persistence.CompanyDAO;
import sg.edu.nus.iss.jass.persistence.JobAdvertDAO;
import sg.edu.nus.iss.jass.persistence.LocationDAO;
import sg.edu.nus.iss.jass.persistence.SkillDAO;
import sg.edu.nus.iss.jass.privilege.AdvertiserRole;
import sg.edu.nus.iss.jass.privilege.SessionContext;
import sg.edu.nus.iss.jass.util.Util;

/**
 * <h5>JobSearchController to manage the JobSearch function activity for both JobSeekers and Advertisers</h5>
 * This controller is called when user clicks on jobseeker or advertiser Search Job Menu option.
 * @author Wang DaYong
 */
public class JobSearchController {
	// TODO getter for list of Company, Location & Skill
	
	private MainFrame mainframe = null;
	private JobSearchFormPanel searchFormPanel;
	private JobAdvertDAO advertDAO;
	private CompanyDAO companyDAO;
	private SkillDAO skillDAO;
	private LocationDAO locationDAO;
	private SearchCriteria searchCriteria;
	
	/**
	 * 
	 * Constructor to instantiate a new JobSearchController object
	 */
	public JobSearchController() {
		this.mainframe = MainController.getInstance().getMainframe();
		advertDAO = new JobAdvertDAO();
		companyDAO = new CompanyDAO();
		skillDAO = new SkillDAO();
		locationDAO = new LocationDAO();
	}
	
	/**
	 * Handle the search request, and display the search result
	 * @param searchCriteria The search parameter
	 */
	public void processSearch(SearchCriteria searchCriteria){
		
		this.searchCriteria = searchCriteria;
		try{
			List<JobAdvert> adverts = retrieveJobAdvert(searchCriteria);
			if(Util.isEmpty(adverts)) {
				searchFormPanel.showMsg(ErrorConstants.ERROR_NO_DATA, false);
				searchFormPanel.clearSearchResult();
			} else {
				searchFormPanel.showSearchResult(adverts);
			}
		}catch(DataStoreException ex){
			searchFormPanel.showMsg(ErrorConstants.ERROR_RETREIVE_DATA, false);
		}
	}
	
	/**
	 * Business logic to search job AD
	 * @param searchCriteria
	 * @return
	 * @throws DataStoreException
	 */
	public List<JobAdvert> retrieveJobAdvert(SearchCriteria searchCriteria) throws DataStoreException{
		if(Util.isEmpty(searchCriteria.getNoOfDays())){
			//job seeker only can view the record that taking effect
			if(SessionContext.getUser().getRole() instanceof AdvertiserRole) {
				searchCriteria.setNoOfDays("");
			} else {
				searchCriteria.setNoOfDays("0");
			}
		}
		
		try {
			List<JobAdvert> adverts = advertDAO.findJobAd(searchCriteria);
			if(Util.isEmpty(adverts)){
				return null;
			}
			for(JobAdvert advert:adverts){
				advert.setCompany(companyDAO.getCompanyById(advert.getCompanyId()));
				if (!Util.isEmpty(advert.getGeographicalLocationId()))
					advert.setGeographicalLocation(locationDAO.getLocationById(advert.getGeographicalLocationId()));
				if (!Util.isEmpty(advert.getSkillIds())) {
					List<Skill> skills = skillDAO.getSkillByIds(advert.getIdList(advert.getSkillIds()));
					for(Skill skill: skills){
						skill.setSkillRef(skillDAO.getSkillRefById(skill.getSkillRefId()));
					}
					advert.setSkills(skills);
				}
			}
			return adverts;
		} catch (DataStoreException e) {
			throw e;
		}
	}
	
	/**
	 * To return all the predefined skills from database
	 * @return Predefined collection of skill
	 */
	public List<SkillReference> getAllSkills(){
		try {
			return (new SkillDAO()).getAllSkills();
		} catch (DataStoreException e) {
			searchFormPanel.showMsg(ErrorConstants.ERROR_RETREIVE_DATA, false);
		}
		return null;
	}
	
	/**
	 * To return all the predefined companies from database
	 * @return Predefined collection of Companies
	 */
	public List<Company> getAllCompanies(){
		try {
			return companyDAO.getAllCompanies();
		} catch (DataStoreException e) {
			searchFormPanel.showMsg(ErrorConstants.ERROR_RETREIVE_DATA, false);
		}
		return null;
	}
	
	/**
	 * To return all the predefined Locations from database
	 * @return Predefined collection of Locations
	 */
	public List<GeographicalLocation> getAllLocations(){
		try {
			return locationDAO.getAllLocations();
		} catch (DataStoreException e) {
			searchFormPanel.showMsg(ErrorConstants.ERROR_RETREIVE_DATA, false);
		}
		return null;
	}

	/**
	 * To launch the JobSearchFormPanel for either Advertiser or JobSeeker role.
	 */
	public void startSearchJob() {
		if(SessionContext.getUser().getRole() instanceof AdvertiserRole) {
			searchFormPanel = new JobSearchFormPanel(mainframe,new DefaultActionPanel(ActionBtnContants.SELECT_ALL,ActionBtnContants.DESELECT_ALL,ActionBtnContants.DELETE), new HeaderPanel("Search Job"));
		} else {
			searchFormPanel = new JobSearchFormPanel(mainframe,new DefaultActionPanel(""), new HeaderPanel("Search Job"));
		}
		searchFormPanel.show();

	}
	
	/**
	 * To launch the respective form panel to view a Job Advertisement or to modify a selected job Advertisement.
	 * To delete a selected Job Advertisement made by the Advertiser.
	 * Each option is selected via a switch statement.  
	 * @param id
	 * @param type
	 * @throws Exception 
	 */
	public void processJobAd(List<JobAdvert> jobAdverts, JobAdFunction type){
		switch(type){
		case view:
			MainController.getInstance().getJobAdvertisementController().startJobAdDetails(jobAdverts.get(0).getId());
			break;
		case modify:
			MainController.getInstance().getJobAdvertisementController().startModifyJobAd(jobAdverts.get(0).getId());
			break;
		case delete:
			if(jobAdverts.size()<=0){
				searchFormPanel.showMsg(ErrorConstants.WARN_NO_JOB_AD_SELECTED, false);
			}
			else
				try {
					MainController.getInstance().getJobAdvertisementController().processDeleteJobAd(jobAdverts);
					this.processSearch(this.searchCriteria);
					this.searchFormPanel.showMsg("Delete Job Advert Success!", true);
				} catch (Exception e) {
					searchFormPanel.showMsg(ErrorConstants.ERROR_DATA_OPERATION, false);
				}			
			break;
		}
	}
	/**
	 * To indicate the functions of the Job Advert.
	 * @param id
	 * @param type
	 * @throws Exception 
	 */
	public enum JobAdFunction{
		view,modify,delete
	}
}
